Skip to content

fix(redact): value-aware secret redaction across all output surfaces (#4 HIGH-2, #7)#123

Merged
ruvnet merged 1 commit into
mainfrom
fix/value-aware-secret-redaction
Jul 7, 2026
Merged

fix(redact): value-aware secret redaction across all output surfaces (#4 HIGH-2, #7)#123
ruvnet merged 1 commit into
mainfrom
fix/value-aware-secret-redaction

Conversation

@ruvnet

@ruvnet ruvnet commented Jul 7, 2026

Copy link
Copy Markdown
Owner

What / why

Fixes HIGH-2 from the AQE beta-feedback (#4): the "bundle is sanitised" promise was value-blind. Five copies of the same recursive redactor (diag.ts, export-config.ts, threat-model.ts, genome.ts, score.ts) keyed only on object-KEY names, so a secret-shaped value in a field not named secret/token/key β€” e.g. a token pasted into a vars entry β€” sailed straight into the harness diag --bundle output that the docs tell users to paste into a GitHub issue.

Also closes finding #7 for this surface: the 5 duplicated redaction regexes become one source of truth.

Change β€” new src/redact.ts

  • looksLikeSecretValue(s) β€” conservative, precision-favouring: known provider prefixes (sk-/ghp_/AKIA/AIza/glpat/xox…), PEM blocks, JWTs, and generic β‰₯40-char mixed-case alphanumeric tokens. The mixed-case+digit rule deliberately excludes lowercase-hex git SHAs, uppercase-hex digests, and dashed UUIDs, so common non-secret identifiers are not redacted.
  • redactSecretsDeep(value, {keyRe, replacement}) β€” redacts by key name and by value shape. Each call site keeps its own keyRe + replacement token (<redacted> for bundles, [REDACTED] for score/genome/threat), so existing behaviour is preserved and only more is redacted (strictly safer).
  • Removes a dead branch in diag.sanitiseManifest (an else if that re-tested the key).

Live-verify (real harness diag --bundle)

"name": "demo",                         # ordinary value β€” kept
"deploy_webhook": "<redacted>",         # secret-shaped value under a NON-secret key β€” redacted
"note": "a1b2c3d4...e7f8a9b0",          # git SHA β€” kept (no false positive)

Raw secret occurrences in the bundle: 0.

Tests

  • 20 new (redact.test.ts): looksLikeSecretValue precision (7 real tokens redact; SHA/UUID/version/path/sentence kept), redactSecretsDeep key + value + nested + array + token cases, and the diag --bundle leak integration (secret-shaped value in a non-secret manifest field is absent from the bundle).
  • Full create-agent-harness suite 381/381; tsc clean.

Not in this PR (noted for follow-up)

secrets.ts HIGH-2 part (a) β€” secrets fetch prints the raw secret to stdout "for piping" (documented behaviour) and validate-token leaks the exact char-length. Changing the print default is a CLI-UX decision better made by a maintainer; happy to follow up.

πŸ€– Generated with claude-flow

 HIGH-2, #7)

Beta feedback #4 (HIGH-2): the "bundle is sanitised" promise was value-blind. Five copies of the same
recursive redactor (diag.ts, export-config.ts, threat-model.ts, genome.ts, score.ts) keyed ONLY on
object-KEY names, so a secret-shaped VALUE in a field NOT named secret/token/key β€” e.g. a token pasted
into a `vars` entry β€” sailed straight into the `harness diag --bundle` output a user pastes into a
GitHub issue.

New src/redact.ts is the single source of truth (also #4 finding #7 β€” was 5 duplicated regexes):
- looksLikeSecretValue(s): conservative, precision-favouring β€” known provider prefixes (sk-/ghp_/AKIA/
  AIza/glpat/xox…), PEM blocks, JWTs, and generic β‰₯40-char MIXED-CASE alphanumeric tokens. The
  mixed-case+digit rule deliberately EXCLUDES lowercase-hex git SHAs, uppercase-hex digests, and dashed
  UUIDs so common non-secret identifiers are not redacted.
- redactSecretsDeep(value, {keyRe, replacement}): redacts by key name AND by value shape; each call site
  keeps its own keyRe + replacement token (`<redacted>` for bundles, `[REDACTED]` for score/genome/threat),
  so existing behaviour is preserved and only MORE is redacted.

Also removes a dead branch in diag.sanitiseManifest (an `else if` that re-tested the key).

Live-verified via real `harness diag --bundle`: a secret-shaped value under a non-secret key redacts to
`<redacted>`, an ordinary value and a git SHA are kept, and the raw secret appears nowhere in the bundle.
20 new tests (redact.ts precision + key/value redaction + the diag-bundle leak integration); full
create-agent-harness suite 381/381; tsc clean.

Co-Authored-By: claude-flow <ruv@ruv.net>
@ruvnet ruvnet merged commit 0d83205 into main Jul 7, 2026
25 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant